/*
 * Copyright (C) 2013 Manuel Peinado
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.pla.lib.view.adapter;

import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;

import com.pla.lib.view.PLA_AdapterView;
import com.pla.lib.view.PLA_AdapterView.OnItemClickListener;
import com.pla.lib.view.PLA_AdapterView.OnItemLongClickListener;
import com.pla.lib.view.listener.EnterMultiChoiceListener;
import com.pla.lib.view.listener.ItemClickInActionModePolicy;

/**
 * MultiChoiceBaseAdapter is an implementation of ListAdapter which adds support for modal multiple
 * choice selection as in the native GMail app.
 * <p>
 * It provides a functionality similar to that of the CHOICE_MODE_MULTIPLE_MODAL ListView mode, but
 * in a manner that is compatible with every version of Android from 2.1. Of course, this requires
 * that your project uses ActionBarSherlock
 * <hr>
 * <p>
 * You'll have to implement the following methods:
 * <p>
 * <b>ActionMode methods:</b>
 * <li><b>onCreateActionMode.</b> Create the action mode that will be displayed when at least one
 * item is selected
 * <li><b>onActionModeClicked.</b> Respond to any of your action mode's actions
 * <p>
 * <br>
 * <b>ListAdapter methods:</b><br>
 * <br>
 * <li><b>getCount.</b> Return the number of items to show
 * <li><b>getItem.</b> Return the item at a given position
 * <li><b>getItemId.</b> Return the id of the item at a given position
 * <li><b>getViewImpl.</b> Returns the view to show for a given position. <b>Important:</b> do not
 * override ListAdapter's getView method, override this method instead
 * <hr>
 * <p>
 * Once you've implemented your class that derives from SelectionAdapter, you'll have to attach it
 * to a ListView like this:
 * <p>
 * <br>
 * <code>
 * MultiChoiceBaseAdapter.setListView(listView);
 * MultiChoiceBaseAdapter.setOnItemClickListener(myItemListClickListener);</code>
 * <p>
 * <br>
 * Do not call setOnItemClickListener on your ListView, call it on the adapter instead
 * </p>
 * <p>
 * <br>
 * Do not forget to derive your activity from one of the ActionBarSherlock activities, except
 * SherlockListActivity
 * </p>
 * <p>
 * <br>
 * Do not forget to call save from your activity's onSaveInstanceState method
 * </p>
 * <p>
 * <br>
 * See the accompanying sample project for a full working application that implements this class
 * </p>
 */
public abstract class PLAMultiChoiceBaseAdapter extends BaseAdapter implements MultiChoiceAdapter {

	private PLAMultiChoiceAdapterHelper helper = new PLAMultiChoiceAdapterHelper(this);

	/**
	 * @param savedInstanceState
	 *            Pass your activity's saved instance state here. This is necessary for the adapter
	 *            to retain its selection in the event of a configuration change
	 */
	public PLAMultiChoiceBaseAdapter(Bundle savedInstanceState) {
		helper.restoreSelectionFromSavedInstanceState(savedInstanceState);
	}

	/**
	 * Sets the adapter view on which this adapter will operate. You should call this method from
	 * the onCreate method of your activity. This method calls setAdapter on the adapter view, so
	 * you don't have to do it yourself
	 * 
	 * @param The
	 *            adapter view (typically a ListView) this adapter will operate on
	 */
	public void setAdapterView(PLA_AdapterView<? super ListAdapter> adapterView) {
		helper.setAdapterView(adapterView);
	}

	/**
	 * Always call this method from your activity's onSaveInstanceState method. This is necessary
	 * for the adapter to retain its selection in the event of a configuration change
	 * 
	 * @param outState
	 *            The same bundle you are passed in onSaveInstanceState
	 */
	public void save(Bundle outState) {
		helper.save(outState);
	}

	/**
	 * Changes the selection of an item. If the item was already in the specified state, nothing is
	 * done. May cause the activation of the action mode if an item is selected an no items were
	 * previously selected
	 * 
	 * @param position
	 *            The position of the item to select
	 * @param checked
	 *            The desired state (selected or not) for the item
	 */
	public void setItemChecked(Object position, boolean checked) {
		helper.setItemChecked(position, checked);
	}

	/**
	 * Returns the indices of the currently selectly items.
	 * 
	 * @return Indices of the currently selectly items. The empty set if no item is selected
	 */
	public List<Object> getCheckedItems() {
		return helper.getCheckedItems();
	}

	/**
	 * Returns the number of selected items
	 * 
	 * @return Number of selected items
	 */
	public int getCheckedItemCount() {
		return helper.getCheckedItemCount();
	}

	/**
	 * Returns true if the item at the specified position is selected
	 * 
	 * @param position
	 *            The item position
	 * @return Whether the item is selected
	 */
	public boolean isChecked(Object position) {
		return helper.isChecked(position);
	}

	public void setItemClickInActionModePolicy(ItemClickInActionModePolicy policy) {
		helper.setItemClickInActionModePolicy(policy);
	}

	public ItemClickInActionModePolicy getItemClickInActionModePolicy() {
		return helper.getItemClickInActionModePolicy();
	}

	/**
	 * Get a View that displays the data at the specified position in the data set. Subclasses
	 * should implement this method instead of the traditional ListAdapter#getView
	 * 
	 * @param position
	 * @param convertView
	 * @param parent
	 * @return
	 */
	protected abstract View getViewImpl(int position, View convertView, ViewGroup parent);

	/**
	 * Convenience method for subclasses that need an activity context
	 */
	protected Context getContext() {
		return helper.getContext();
	}

	//
	// BaseAdapter implementation
	//

	@Override
	public void cancelAllSeleted() {
		helper.cancelAllSeleted();
	}

	@Override
	public void registerMultiChoiceListener(EnterMultiChoiceListener listener) {
		helper.registerMultiChoiceListener(listener);
	}

	@Override
	public final View getView(int position, View convertView, ViewGroup parent) {
		View viewWithoutSelection = getViewImpl(position, convertView, parent);
		return helper.getView(position, viewWithoutSelection);
	}

	@Override
	public void removeCheckState(Object id) {
		helper.removeCheckState(id);
	}

	@Override
	public void setCheckedItems(List<? extends Object> items) {
		helper.setCheckedItems(items);
	}

	@Override
	public void setAdapterView(AdapterView<? super BaseAdapter> adapterView) {
	}

	@Override
	public void setOnItemLongClickListener(android.widget.AdapterView.OnItemLongClickListener listener) {
		// TODO Auto-generated method stub

	}

	/**
	 * Register a callback to be invoked when an item in the associated AdapterView has been clicked
	 * 
	 * @param listener
	 *            The callback that will be invoked
	 */
	@Override
	public void setOnItemClickListener(android.widget.AdapterView.OnItemClickListener listener) {
	}

	@Override
	public void setPlaOnItemLongClickListener(OnItemLongClickListener listener) {
		helper.setOnItemLongClickListener(listener);
	}

	@Override
	public void setPlaOnItemClickListener(OnItemClickListener listener) {
		helper.setOnItemClickListener(listener);
	}

}